package util.io;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import util.Contestant;
import util.ContestantLap;
import util.TimeData;

/**
 * Import content from at text file.
 * 
 * @author Team07
 */
public abstract class FileImporter {

	protected TimeData data;

	/**
	 * Constructor which creates a FileImporter
	 */
	public FileImporter() {
		data = new TimeData();
	}

	/**
	 * Imports a file into this instance of the FileImporter. The type of the
	 * file is automatically determined from it's name.
	 * 
	 * @param fileName
	 *            Full path to the file.
	 * @throws IOException
	 *             exception thrown if the file doesn't exist or if access to it
	 *             was denied.
	 */
	public void loadFile(String fileName) throws IOException {
		Pattern myPattern = Pattern
		.compile(".*[\\/]?(mal|start|namn)[^\\/]*\\.txt");
		Matcher myMatcher = myPattern.matcher(fileName);

		if (myMatcher.matches()) {
			if (myMatcher.group(1).equals("mal")) {
				loadFinish(fileName);
			} else if (myMatcher.group(1).equals("start")) {
				loadStart(fileName);
			} else if (myMatcher.group(1).equals("namn")) {
				loadName(fileName);
			}
		} else {
			if(fileName.charAt(0) != '-'){
				throw new IllegalArgumentException("Filetype not regonized: " + fileName);
			}
		}
	}

	/**
	 * Loads start times from the specified file. Abstract method implemented in
	 * subclasses.
	 * 
	 * @param fileName
	 *            the file to be parsed
	 * @throws IOException
	 *             if the file cannot be found or similiar.
	 */
	protected abstract void loadStart(String fileName) throws IOException;

	/**
	 * Loads finish times from the specified file. Abstract method implemented
	 * in subclasses.
	 * 
	 * @param fileName
	 *            the file to be parsed
	 * @throws IOException
	 *             if the file cannot be found or similiar.
	 */
	protected abstract void loadFinish(String fileName) throws IOException;

	/**
	 * Loads names from the specified file.
	 * 
	 * @param fileName
	 *            the file to be parsed
	 * @throws IOException
	 *             if the file cannot be found or similiar.
	 */
	protected void loadName(String fileName) throws IOException {
		ArrayList<String> fileLines = loadData(fileName);

		String category = "";

		for (String line : fileLines) {
			if (!Character.isDigit(line.charAt(0))) {
				if (line.contains(";")) { 				// Rader med rubriker
					data.setNewNameIdientifier(line.split(";", 2)[1].trim());
				} else {
					category = line;
				}
				continue;
			}

			try {
				String[] field = line.split(";", 2);
				Contestant c = getContestant(Integer.valueOf(field[0]));
				c.setName(field[1].trim());
				c.setCategory(category);
			} catch (NumberFormatException e) {
				continue;
			}
		}
	}

	/**
	 * Gets the internal TimeData object that this instance of the FileImporter
	 * is working with.
	 * 
	 * @return The TimeData object.
	 */
	public TimeData getData() {
		return data;
	}

	/**
	 * Tries to get a contestant with the given id from the temporary timedata.
	 * If it doesn't exists a new one will be created.
	 * 
	 * @param id
	 *            The id to look for
	 * @return The contestant
	 */
	protected Contestant getContestant(int id) {
		Contestant c = data.getContestant(id);

		if (c == null) {
			c = new ContestantLap(id);
			data.putContestant(c);
		}
		return c;
	}

	/**
	 * Loads the timedata from a given file and returns the result as an
	 * ArrayList<String>
	 * 
	 * @param fileName
	 *            The specified filename
	 * @return An ArrayList<String> representing the file
	 * @throws IOException
	 *             Exception thrown if the file doesn't exist or if access to it
	 *             was denied.
	 * 
	 */
	public static ArrayList<String> loadData(String fileName)
	throws IOException {
		ArrayList<String> fileLines = new ArrayList<String>();
		FileReader fileReader = new FileReader(fileName);
		BufferedReader bufferReader = new BufferedReader(fileReader);
		String line = bufferReader.readLine();
		if (line == null) {
			throw new IOException();
		}
		line = line.trim();
		while (line != null && !line.equals("")) {
			fileLines.add(line);
			line = bufferReader.readLine();
		}
		bufferReader.close();
		fileReader.close();
		return fileLines;
	}

	/**
	 * Returns an IdTimePair wich is used by stage laps
	 * 
	 * @param fileLines The list of times to be parsed
	 * @return Times paired together with ID's
	 */
	protected static IdTimePair[] parseTime(ArrayList<String> fileLines) {
		IdTimePair[] pairs = new IdTimePair[fileLines.size()];

		for (int i = 0; i < fileLines.size(); i++) {
			String[] field = fileLines.get(i).split(";");
			String[] splittedDate = field[1].trim().split("\\.");

			int h = Integer.parseInt(splittedDate[0]);
			int m = Integer.parseInt(splittedDate[1]);
			int s = Integer.parseInt(splittedDate[2]);

			long ms = s * 1000 + m * 1000 * 60 + h * 1000 * 60 * 60;

			IdTimePair pair = new IdTimePair();
			pair.id = Integer.parseInt(field[0].trim());
			pair.ms = ms;

			pairs[i] = pair;
		}

		return pairs;
	}

	/**
	 * Inner class for representing timepairs wich is used in stage lap
	 * competitions
	 * 
	 * @author team07
	 */
	protected static class IdTimePair {
		public int id;
		public long ms;
	}
}
